home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
BCI NET
/
BCI NET Dec 94.iso
/
archives
/
programming
/
source
/
vmem.lha
/
vmem.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-12-19
|
22KB
|
879 lines
/*
** VMEM - a virtual memory manager for the Amiga operating system
**
** Version 0.1 ©1990 by Edward Hutchins
** Based in part on the SetCPU program by Dave Haynie
** Authors:
**
** Edward Hutchins: eah1@cec1.wustl.edu
** Loren Rittle: l-rittle@uiuc.edu
**
** Revisions:
** 10/29/91 cleaned up code somewhat - Ed.
** 12/19/91 made the spy faster with SpyPenCache - Ed.
** 12/19/91 code released as freeware under the GNU general public license - Ed.
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 1, or (at your option)
** any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
**
*/
#include "vmem.h"
/*
** typedefs and defines
*/
#define VMEM_VERSION "0.4" /* vmem version */
#define VMEM_NAME "virtual memory" /* memory pool name */
#define VMEM_BASE 0x01000000 /* virt mem base addr */
#define VMEM_PRI 20 /* allocation priority */
#define DEF_SWAP_FILE_NAME "work:.VMEM_PAGES" /* should be SYS: */
#define DEF_NUMFRAMES 0x80 /* 1M of frames */
#define DEF_NUMPAGES 0x200 /* 4M of virt mem */
#define INITIAL_SHIFT 5 /* 5 + 14 + 13 == 32 */
#define PAGE_SIZE 0x2000 /* 8k pages */
#define PAGE_SIZE_MASK 0x1FFF /* mask off 8k */
#define PAGE_SIZE_INDEX 13 /* 8k page offset bits */
#define PAGE_TABLE_INDEX 14 /* TIA index bits */
#define PAGE_TABLE_MIN 0x800 /* 16M of 8k pages */
#define PAGEDAEMON_PRI 50 /* VERY high priority */
#define AGEING_PERIOD 100000 /* 0.1 second */
#define FASTPUB (MEMF_FAST | MEMF_PUBLIC) /* fast public memory */
/* spy stuff */
#define WIDTH 320
#define HEIGHT 32
#define DEPTH 3
#define MAX_PEN 8
/*
** globals
*/
struct ExecBase *ExecBase;
struct GfxBase *GfxBase;
struct IntuitionBase *IntuitionBase;
struct Window *window;
struct RastPort *RP;
UWORD NumFrames = DEF_NUMFRAMES; /* number of frames */
UWORD NumPages = DEF_NUMPAGES; /* number of pages */
CPTR ROMBase; /* ROMs mapped to this RAM */
CPTR FrameBase; /* frame table */
PFRAME_DESC FrameTable; /* frame descriptors */
PPD_SHORT PageTable; /* page table */
CPTR SysBusErrHandler; /* default bus fault vector */
ULONG SwapFile; /* handle to swap file */
ULONG PageDaemonSig; /* daemon's signal */
struct Task *PageDaemonTask; /* the pager (us for now) */
struct MemHeader *FastMemHeader; /* public memory area */
struct MinList PageFaultList; /* queue faults here */
char SwapFileName[80]; /* swap file name */
WORD PendingPageFaults; /* page faults to be served */
/* this will break once NumPages gets parsed from the command line... */
BYTE SpyPenCache[PAGE_TABLE_MIN + DEF_NUMPAGES];
#define VMEM_LENGTH (NumPages * PAGE_SIZE) /* virt mem size */
#define VMEM_END (VMEM_BASE + VMEM_LENGTH) /* end of virt mem */
/* get a frame index from a page address */
#define PAGE_TO_FRAME(pd) ((((pd)&PD_ADDR_MASK)-(ULONG)FrameBase)/PAGE_SIZE)
/*
** locals
*/
UWORD ctable[] =
{0x0000, 0x0222, 0x0630, 0x0f00, 0x000f, 0x0070, 0x0304, 0x0740 };
/* spy pen types (map to colors above) */
enum { PEN_UNUSED, PEN_VIRT, PEN_INVALID, PEN_MOD,
PEN_USED, PEN_WP, PEN_CI, PEN_FRAME };
/*
** We don't need any termination routines
*/
VOID MemCleanup(VOID) {}
/*
** AllocBlocks - allocate memory aligned by lBound+1
*/
static void *AllocBlocks( ULONG lSize, ULONG lBound )
{
void *mem, *aligned;
if (!(mem = AllocMem( lSize + lBound, FASTPUB ))) return( NULL );
Forbid();
aligned = (void *)(((ULONG)mem + lBound) & ~(lBound));
FreeMem( mem, lSize + lBound );
mem = AllocAbs( lSize, aligned );
Permit();
return( mem );
}
/*
** AllocVMem - find the fast memory list, allocate needed physical space
*/
BOOL AllocVMem(VOID)
{
ULONG FrameSize = NumFrames * PAGE_SIZE;
ULONG FrameTableSize = NumFrames * sizeof(FRAME_DESC);
ULONG PageTableSize = (PAGE_TABLE_MIN + NumPages) * sizeof(PD_SHORT);
BOOL bSuccess = FALSE;
/* prevent mucking about with the MemLists */
Disable();
/* find a fast+public memory MemHeader for the fault nodes */
/* note: this works because lh_Head and ln_Succ are the same */
FastMemHeader = (struct MemHeader *)&(ExecBase->MemList);
if (FastMemHeader == NULL)
{
Enable();
goto BailOut;
}
for (;;)
{
FastMemHeader = (struct MemHeader *) FastMemHeader->mh_Node.ln_Succ;
if (FastMemHeader == NULL) goto BailOut;
if ((FastMemHeader->mh_Attributes & FASTPUB) == FASTPUB) break;
}
Enable();
/* allocate in this order to minimize fragging */
if (!(FrameBase = (CPTR)AllocBlocks( FrameSize, PAGE_SIZE_MASK )))
goto BailOut;
if (!(ROMBase = (CPTR)AllocBlocks( ROMSIZE, PAGE_SIZE_MASK )))
goto BailOut;
/* the !@#%!&* CRP needs to be aligned to 16-byte boundaries */
if (!(PageTable = (PPD_SHORT)AllocBlocks( PageTableSize, 15 )))
goto BailOut;
if (!(FrameTable = (PFRAME_DESC)AllocBlocks( FrameTableSize, 15 )))
goto BailOut;
bSuccess = TRUE;
/* come here to bomb */
BailOut:
return (bSuccess);
}
/*
** SetPageTableFlags - set flags in the page table over a range of addresses
*/
VOID SetPageTableFlags(ULONG begad, ULONG endad, ULONG Flags)
{
while (begad < endad)
{
PageTable[begad / PAGE_SIZE] |= Flags;
begad += PAGE_SIZE;
}
}
/*
** ClearPageTableFlags - clear flags in the page table over a range of addresses
*/
VOID ClearPageTableFlags(ULONG begad, ULONG endad, ULONG Flags)
{
while (begad < endad)
{
PageTable[begad / PAGE_SIZE] &= ~Flags;
begad += PAGE_SIZE;
}
}
/*
** This routine creates the Fast ROM and sets up memory.
**
** Address:
** 31 23 15 7 0
** +------+--------------+----------+
** | IS 5 | TIA 14 | PS 13 | 13 bits = 8K pages
** +------+--------------+----------+
**
** First 5 bits of logical address -> shifted into the bit bucket
** next 14 bits of logical address -> index into PageTable (level A)
** last 13 bits of logical address -> offset into page
*/
BOOL CreatePageTable(VOID)
{
ULONG i, myCRP[2], myTC;
#if defined(DEBUG)
printf("AllocVMem()\n");
#endif
/* allocate all needed memory */
if (!AllocVMem()) return (FALSE);
#if defined(DEBUG)
printf("CopyMemQuick()\n");
#endif
/* Here I set up the ROM, as quickly as possible! */
CopyMemQuick((ULONG *)ROMBASE, (ULONG *)ROMBase, ROMSIZE);
#if defined(DEBUG)
printf("Translation setup...\n");
#endif
/* transparent translation of existing address space... */
for (i = 0x00000000; i < ROMBASE; i += PAGE_SIZE)
{
PageTable[i / PAGE_SIZE] = PD_ADDR(i) | PD_DT_PAGE;
}
/* ...except re-map the ROM image and write protect it... */
for (i = ROMBASE; i < 0x00FFFFFF; i += PAGE_SIZE)
{
PageTable[i / PAGE_SIZE] = PD_ADDR(ROMBase + (i - ROMBASE)) | PD_WP | PD_DT_PAGE;
}
/* ...as well as the physical memory containing the ROM image */
SetPageTableFlags( (ULONG)ROMBase, (ULONG)ROMBase + ROMSIZE, PD_WP );
/*
** cache-inhibit chip memory and custom registers
**
** $00000000
** | 2M chip memory, cache inhibit
** $001FFFFF
** $00200000
** | 8M fast ram, public
** $00BFFFFF
** $00A00000
** | 2M reserved area, cache inhibit anyway
** $00BFFFFF
** $00C00000
** | 1M fast (slow really) ram on some machines, public
** $00CFFFFF
** $00D00000
** | 2M custom chip area, cache inhibit
** $00F7FFFF
** $00F80000
** | 256K system rom area (part mapped to FASTROM)
** $00FFFFFF
** $01000000
** | (up to) 16M virtual memory area
** $01FFFFFF
*/
/* set up cache-inhibit */
SetPageTableFlags(0x00000000, 0x001FFFFF, PD_CI);
SetPageTableFlags(0x00A00000, 0x00BFFFFF, PD_CI);
SetPageTableFlags(0x00D00000, 0x00F7FFFF, PD_CI);
/* map the first of the virtual pages to the available frames */
for (i = 0; i < NumFrames; ++i)
{
FrameTable[i].Age = 0;
FrameTable[i].PageIndex = PAGE_TABLE_MIN + i;
PageTable[PAGE_TABLE_MIN + i] = PD_ADDR(FrameBase + (i * PAGE_SIZE)) | PD_DT_PAGE;
}
/* clear out the rest of virtual memory to invalid status */
for (i = NumFrames; i < NumPages; ++i)
{
PageTable[PAGE_TABLE_MIN + i] = PD_DT_INVALID;
}
/*
** Now I have to set up the MMU. The CPU Root Pointer tells the MMU about
** the table I've set up, and the Translation Control register will turn
** the thing on. Note that the first half of the CRP is control data, the
** second the address of my table.
*/
#if defined(DEBUG)
printf("CRP and TC Setup...\n");
#endif
Disable();
SetTC(0);
myCRP[0] = CRP_LIMIT(PAGE_TABLE_MIN + NumPages - 1) | CRP_SG | CRP_DT_V4BYTE;
myCRP[1] = (ULONG) PageTable;
SetCRP(myCRP);
myTC = TC_ENB | TC_IS(INITIAL_SHIFT) | TC_TIA(PAGE_TABLE_INDEX) |
TC_TIB(0) | TC_TIC(0) | TC_TID(0) | TC_PS(PAGE_SIZE_INDEX);
SetTC(myTC);
Enable();
return (TRUE);
}
/*
** AddVirtMem - add the virtual memory to the system free list
*/
VOID AddVirtMem(VOID)
{
static char VirtMemName[] = VMEM_NAME;
/* the page table better have a valid descriptor for the first page... */
AddMemList(VMEM_LENGTH, MEMF_FAST, VMEM_PRI, VMEM_BASE, VirtMemName);
}
/*
** ShowFrameTableAges - show the page age table
*/
VOID ShowFrameTableAges(VOID)
{
PFRAME_DESC pFrame = &FrameTable[0];
PFRAME_DESC pFrameEnd = &FrameTable[NumFrames];
PFRAME_DESC pOldest = pFrame;
UWORD FrameIndex = 0;
while (pFrame < pFrameEnd)
{
printf("%d(%4.4x,%4.4x) ", FrameIndex, pFrame->Age, pFrame->PageIndex);
if (FrameIndex % 4 == 0) printf("\n");
++FrameIndex, ++pFrame;
}
printf("\n\n");
}
/*
** AgeFrameTable - age the frame table
*/
VOID AgeFrameTable(VOID)
{
PFRAME_DESC pFrame = &FrameTable[0];
PFRAME_DESC pFrameEnd = &FrameTable[NumFrames];
Disable();
while (pFrame < pFrameEnd)
{
PPD_SHORT pTbl = &PageTable[pFrame->PageIndex];
if (*pTbl & PD_USED)
{
*pTbl &= ~PD_USED;
pFrame->Age /= 2;
}
else if (pFrame->Age < AGE_MAX) ++(pFrame->Age);
++pFrame;
}
Enable();
}
/*
** CreateSwapFile - open and allocate the swap file
**
** Call AFTER AllocVMem is done
*/
BOOL CreateSwapFile(VOID)
{
ULONG Offset, SizeNeeded = NumPages * PAGE_SIZE;
ULONG BuffSize = NumFrames * PAGE_SIZE;
BOOL bSuccess = FALSE;
#if defined(DEBUG)
printf("opening file, ");
#endif
/* get an exclusive lock on this file */
SwapFile = Open(SwapFileName, MODE_OLDFILE);
if (SwapFile == 0)
{
SwapFile = Open(SwapFileName, MODE_NEWFILE);
if (SwapFile == 0) return (FALSE);
}
/* make sure the file is at least big enough */
if (Seek(SwapFile, 0, OFFSET_END) == -1) goto Abort;
if ((Offset = Seek(SwapFile, 0, OFFSET_CURRENT)) == -1) goto Abort;
/* is it already big enough? */
if (Offset >= SizeNeeded)
{
bSuccess = TRUE;
goto Abort;
}
#if defined(DEBUG)
printf("clearing buffer, ");
#endif
/* clear out the buffer */
{
char *p = FrameBase;
char *e = FrameBase + BuffSize;
while (p < e) *p++ = '\0';
}
SizeNeeded -= Offset;
#if defined(DEBUG)
printf("writing (%ld) ", SizeNeeded);
#endif
while (SizeNeeded > BuffSize)
{
if (Write(SwapFile, FrameBase, BuffSize) != BuffSize) goto Abort;
SizeNeeded -= BuffSize;
#if defined(DEBUG)
printf(". ");
#endif
}
if (Write(SwapFile, FrameBase, SizeNeeded) == SizeNeeded) bSuccess = TRUE;
Abort:
#if defined(DEBUG)
printf("closing\n");
#endif
Close(SwapFile);
return (bSuccess);
}
/*
** StealPage - choose the oldest page and discard it, return it's index
*/
UWORD StealPage(VOID)
{
PFRAME_DESC pFrame = &FrameTable[0];
PFRAME_DESC pFrameEnd = &FrameTable[NumFrames];
PFRAME_DESC pOldest = pFrame;
UWORD Wage = WAGE(pOldest);
UWORD FrameIndex;
PD_SHORT pd;
Disable();
/* find the oldest page */
while (++pFrame < pFrameEnd) if (WAGE(pFrame) > Wage)
{
pOldest = pFrame;
Wage = WAGE(pOldest);
}
FrameIndex = (((ULONG) pOldest - (ULONG) FrameTable) / sizeof(FRAME_DESC));
/* mark the stolen page as invalid */
pd = PageTable[pOldest->PageIndex];
PageTable[pOldest->PageIndex] = PD_DT_INVALID;
Enable();
/* if the stolen page has been modified, we need to save it */
if (pd & PD_MOD)
{
ULONG FrameOffset = FrameIndex * PAGE_SIZE;
ULONG PageOffset = (pOldest->PageIndex * PAGE_SIZE) - VMEM_BASE;
if ((SwapFile = Open(SwapFileName, MODE_OLDFILE)) == 0)
{
#if defined(DEBUG)
printf("StealPage open file failed! (%s)\n", SwapFileName);
#endif
Alert(-1L, 1);
}
Seek(SwapFile, PageOffset, OFFSET_BEGINNING);
Write(SwapFile, FrameBase + FrameOffset, PAGE_SIZE);
Close(SwapFile);
#if defined(DEBUG_PAGING)
printf("page %d (%lx) swapped out, ", pOldest->PageIndex, PageOffset);
#endif
}
return (FrameIndex);
}
/*
** LockPage - check if a page is swapped in, and lock it if so
*/
BOOL LockPage(CPTR Address)
{
PD_SHORT pd;
if (Address < VMEM_BASE) return (TRUE);
pd = PageTable[Address / PAGE_SIZE];
/* the page is swapped out, so swap it in later */
if ((pd & PD_DT_MASK) == PD_DT_INVALID) return (FALSE);
/* hopefully we won't get paged out right away */
FrameTable[PAGE_TO_FRAME(pd)].Age = 0;
return (TRUE);
}
/*
** LoadPage - load a swapped out page, stealing unlocked pages only
*/
VOID LoadPage(CPTR Address)
{
UWORD PageIndex = Address / PAGE_SIZE;
ULONG PageOffset = (PageIndex * PAGE_SIZE) - VMEM_BASE;
UWORD FrameIndex;
ULONG FrameOffset;
/* has this page already been fixed? */
if ((PageTable[PageIndex] & PD_DT_MASK) == PD_DT_PAGE) return;
FrameOffset = (FrameIndex = StealPage()) * PAGE_SIZE;
if ((SwapFile = Open(SwapFileName, MODE_OLDFILE)) == 0)
{
#if defined(DEBUG)
printf("LoadPage open file failed! (%s)\n", SwapFileName);
#endif
Alert(-1L, 2);
}
Seek(SwapFile, PageOffset, OFFSET_BEGINNING);
Read(SwapFile, FrameBase + FrameOffset, PAGE_SIZE);
Close(SwapFile);
#if defined(DEBUG_PAGING)
printf("page %d (%lx) swapped in\n", PageIndex, PageOffset);
#endif
FrameTable[FrameIndex].Age = 0;
FrameTable[FrameIndex].PageIndex = PageIndex;
PageTable[PageIndex] = PD_ADDR(FrameBase + FrameOffset) | PD_DT_PAGE;
}
/*
** CorrectPageFault - lock and load all needed pages, signal task to restart
*/
BOOL CorrectPageFault(VOID)
{
PFaultNode FaultNode;
CPTR Faults[4]; /* Data Fault (LSB and MSB), stage B, stage C */
UWORD FaultCount = 0;
UWORD Format;
UWORD PPF;
static UWORD OldFormat = 0;
static UWORD SSW = 0;
UWORD bDiff = FALSE;
Disable();
FaultNode = (PFaultNode) RemHead((struct List *) & PageFaultList);
Enable();
if (!FaultNode) return (FALSE);
Format = FaultNode->Fault.S.VectorOffset & SF_FORMAT_MASK;
#if defined(DEBUG)
PPF = --PendingPageFaults;
if (PPF)
printf("PPF=%d ", PPF);
if (Format != OldFormat)
OldFormat = Format, bDiff = TRUE;
if (FaultNode->Fault.S.SpecialStatusReg != SSW)
SSW = FaultNode->Fault.S.SpecialStatusReg, bDiff = TRUE;
if (bDiff)
printf("Format [%4.4x] SSW = %4.4x\n", OldFormat, SSW);
#endif
/* Data Fault is the same for both long and short frames */
if (!LockPage(FaultNode->Fault.S.DataCycleFaultAddr))
Faults[FaultCount++] = FaultNode->Fault.S.DataCycleFaultAddr;
/* check LSB of Data Fault */
if (!LockPage(FaultNode->Fault.S.DataCycleFaultAddr + 3))
Faults[FaultCount++] = FaultNode->Fault.S.DataCycleFaultAddr + 3;
if (Format == SSF_FORMAT)
{
/* stage B address is PC+4, stage C is PC+2 */
if (!LockPage(FaultNode->Fault.S.PC + 4))
Faults[FaultCount++] = FaultNode->Fault.S.PC + 4;
if (!LockPage(FaultNode->Fault.S.PC + 2))
Faults[FaultCount++] = FaultNode->Fault.S.PC + 2;
}
else /* must be LSF_FORMAT */
{
/* stage B address is in stack frame, stage C is at B-2 */
if (!LockPage(FaultNode->Fault.L.StageBAddress))
Faults[FaultCount++] = FaultNode->Fault.L.StageBAddress;
if (!LockPage(FaultNode->Fault.L.StageBAddress - 2))
Faults[FaultCount++] = FaultNode->Fault.L.StageBAddress - 2;
}
/* load all faulted pages */
while (FaultCount--) LoadPage(Faults[FaultCount]);
/* wake up the sleeping task (it does the rest) */
Signal(FaultNode->FaultedTask, 1 << FaultNode->RestartSigNum);
return (TRUE);
}
/*
** ShowUsage - explain VMEM
*/
VOID ShowUsage(VOID)
{
printf("\2330;33mVMem " VMEM_VERSION " ©1990 by Edward Hutchins\2330m\n");
printf("Usage: VMem [-f <swapfile>] [-p <phys pages>] [-v <virt pages>]\n");
printf("Note: the default swap file is " DEF_SWAP_FILE_NAME "\n");
}
/*
** Spy - spy on memory usage
*/
void Spy(void)
{
UWORD totalpages = PAGE_TABLE_MIN + NumPages;
WORD xoff = WIDTH - totalpages / 16;
while (1)
{
UWORD i = totalpages;
while (i--)
{
PD_SHORT pd = PageTable[i];
BYTE pen;
if (i < PAGE_TABLE_MIN)
{
PageTable[i] &= ~(PD_MOD | PD_USED);
pen = PEN_UNUSED;
}
else pen = PEN_VIRT;
if ((pd & PD_DT_MASK) == PD_DT_INVALID) pen = PEN_INVALID;
else if (pd & PD_MOD) pen = PEN_MOD;
else if (pd & PD_USED) pen = PEN_USED;
else if (pd & PD_WP) pen = PEN_WP;
else if (pd & PD_CI) pen = PEN_CI;
if (pen != SpyPenCache[i])
{
SetAPen(RP, SpyPenCache[i] = pen);
WritePixel(RP, 80 + (i / 16), 8 + (i & 15));
}
}
}
}
/*
** SetupSpy - create the spy task
*/
void SetupSpy(void)
{
if (!(window = OpenScrn(WIDTH, HEIGHT, DEPTH, 0, 0))) return;
/* sig = 1 << (window->UserPort->mp_SigBit); */
LoadRGB4(ViewPortAddress(window), ctable, MAX_PEN);
RP = window->RPort;
SetRast(RP, PEN_FRAME);
CreateTask ("VMEM Spy", -1L, Spy, 4096);
}
/*
** OpenLibs - open the needed libraries
*/
void OpenLibs( void )
{
/* we need to open this for some reason */
ExecBase = (struct ExecBase *) OpenLibrary("exec.library", 0);
if (!ExecBase) exit( 20 );
GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0);
if (!GfxBase) exit( 20 );
IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0);
if (!IntuitionBase) exit( 20 );
}
/*
** main - VMEM main entry point
*/
int main(int argc, char *argv[])
{
ULONG cacr, cpu, fpu, mmu = 0;
struct MsgPort *AgePort = NULL;
struct timerequest *TimerReq = NULL;
ULONG AgeSig;
ULONG Signals;
UBYTE DaemonSigNum;
OpenLibs();
#if defined(DEBUG)
printf("This is the debugging version of VMEM\n\n");
#endif
/* If they're just asking for help */
if (argc >= 2 && argv[1][0] == '?')
{
ShowUsage();
exit(0);
}
/* get the system setup */
cpu = GetCPUType();
fpu = GetFPUType();
mmu = GetMMUType();
/* trap silly users */
if (cpu < 68020 || !mmu)
{
printf("Sorry, your system doesn't have the balls for VMEM!\n");
exit(0);
}
/* allocate the paging daemon's signal */
if ((DaemonSigNum = AllocSignal(-1)) == -1) goto Abort;
/* allocate the ageing timer port */
AgePort = CreatePort(NULL, 0);
if (AgePort == NULL) goto Abort;
TimerReq = (PTIMER_REQ) CreateExtIO(AgePort, sizeof(TIMER_REQ));
if (TimerReq == NULL) goto Abort;
if (OpenDevice(TIMERNAME, UNIT_VBLANK, (struct IORequest *)TimerReq, 0)) goto Abort;
/* parse arguments someday... */
strcpy(SwapFileName, DEF_SWAP_FILE_NAME);
#if 0
if (argc > 1)
{
for (i = 1; i < argc; ++i)
{
}
}
#endif
/* set up both the instruction and data caches */
cacr = (CACR_INST | CACR_DATA) << CACR_WALLOC;
cacr |= (CACR_INST | CACR_DATA) << CACR_BURST;
cacr |= (CACR_INST | CACR_DATA) << CACR_CLEAR;
cacr |= (CACR_INST | CACR_DATA) << CACR_ENABLE;
SetCACR(cacr);
#if defined(DEBUG)
printf("MMU Check\n");
#endif
/* see if someone's using the MMU already */
if (GetTC() & TC_ENB) printf("MMU already in use, resetting...\n");
#if defined(DEBUG)
printf("CreatePageTable()\n");
#endif
/* create the low-level paging tables and set up the MMU */
if (!CreatePageTable())
{
printf("Error: not enough physical memory\n");
goto Abort;
}
#if defined(DEBUG)
printf("CreateSwapFile()\n");
#endif
/* open the swap file and make sure it's big enough */
if (!CreateSwapFile())
{
printf("Error: failed to create swap file\n");
goto Abort;
}
/* initialize misc variables */
NewList((struct List *) & PageFaultList);
PageDaemonTask = FindTask(NULL);
PageDaemonSig = 1 << DaemonSigNum;
AgeSig = 1 << AgePort->mp_SigBit;
/* queue a timer request to get us started */
TimerReq->tr_node.io_Command = TR_ADDREQUEST;
TimerReq->tr_time.tv_secs = 0;
TimerReq->tr_time.tv_micro = AGEING_PERIOD;
SendIO((struct IORequest *) TimerReq);
/*
** The point of no return...
*/
SetupSpy();
SetTaskPri(PageDaemonTask, PAGEDAEMON_PRI);
#if defined(DEBUG)
printf("InsertFaultHandler()\n");
#endif
InsertFaultHandler();
#if defined(DEBUG)
printf("AddVirtMem()\n");
#endif
AddVirtMem();
/*
** This task never exits (system failure would result)
*/
#if defined(DEBUG)
printf("Waiting on %lx\n", PageDaemonSig | AgeSig);
#endif
for (;;)
{
Signals = Wait(PageDaemonSig | AgeSig);
if (Signals & AgeSig)
{
#if defined(DEBUG_AGEING)
static int nCnt = 0;
if (nCnt++ % 50 == 0) ShowFrameTableAges();
#endif
GetMsg(AgePort);
AgeFrameTable();
TimerReq->tr_node.io_Command = TR_ADDREQUEST;
TimerReq->tr_time.tv_secs = 0;
TimerReq->tr_time.tv_micro = AGEING_PERIOD;
SendIO((struct IORequest *) TimerReq);
}
if (Signals & PageDaemonSig) while (CorrectPageFault()) ;
}
Abort: /* we only come here if there was a problem */
if (DaemonSigNum != -1) FreeSignal(DaemonSigNum);
if (AgePort) DeletePort(AgePort);
if (TimerReq) DeleteExtIO((struct IORequest *) TimerReq);
exit(30);
}